/**
 * 
 */
package com.sc.softmgr.common.configuration;

import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import com.alibaba.druid.pool.DruidDataSource;
import com.sc.softmgr.common.data.DataSourcePropertiesData;

/**
 * 
 * @content Druid的DataSources配置
 * 
 * @date 2017年5月9日
 * 
 * @author OprCalf
 * 
 */
@Configuration
@ConfigurationProperties
@EnableTransactionManagement
public class DataSourceConfiguration {

	private final Logger log = Logger.getLogger(this.getClass());

	@Autowired
	private DataSourcePropertiesData dataSourceProperties;

	@Bean(destroyMethod = "close", initMethod = "init")
	@Primary // 在同样的DataSource中，首先使用被标注的DataSource
	public DataSource dataSource() {
		DruidDataSource datasource = new DruidDataSource();
		datasource.setUrl(dataSourceProperties.getUrl());
		datasource.setUsername(dataSourceProperties.getUserName());
		datasource.setPassword(dataSourceProperties.getPassword());
		datasource.setDriverClassName(dataSourceProperties.getDriverClassName());

		// configuration
		datasource.setInitialSize(dataSourceProperties.getInitialSize());
		datasource.setMinIdle(dataSourceProperties.getMinIdle());
		datasource.setMaxActive(dataSourceProperties.getMaxActive());
		datasource.setMaxWait(dataSourceProperties.getMaxWait());
		datasource.setTimeBetweenEvictionRunsMillis(dataSourceProperties.getTimeBetweenEvictionRunsMillis());
		datasource.setMinEvictableIdleTimeMillis(dataSourceProperties.getMinEvictableIdleTimeMillis());
		datasource.setValidationQuery(dataSourceProperties.getValidationQuery());
		datasource.setTestWhileIdle(dataSourceProperties.isTestWhileIdle());
		datasource.setTestOnBorrow(dataSourceProperties.isTestOnBorrow());
		datasource.setTestOnReturn(dataSourceProperties.isTestOnReturn());
		datasource.setPoolPreparedStatements(dataSourceProperties.isPoolPreparedStatements());
		datasource.setMaxPoolPreparedStatementPerConnectionSize(
				dataSourceProperties.getMaxPoolPreparedStatementPerConnectionSize());
		try {
			datasource.setFilters(dataSourceProperties.getFilters());
		} catch (SQLException e) {
			log.error("filters出现错误", e);
		}

		return datasource;
	}

	@Bean
	@Primary
	public PlatformTransactionManager txManager(DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}

	@Bean(name = "transactionInterceptor")
	public TransactionInterceptor transactionInterceptor(PlatformTransactionManager platformTransactionManager) {
		TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
		// 事物管理器
		transactionInterceptor.setTransactionManager(platformTransactionManager);
		Properties transactionAttributes = new Properties();
		// 新增
		transactionAttributes.setProperty("insert*", "PROPAGATION_REQUIRED,-Exception");
		// 修改
		transactionAttributes.setProperty("update*", "PROPAGATION_REQUIRED,-Exception");
		// 删除
		transactionAttributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception");
		// 查询
		transactionAttributes.setProperty("select*", "PROPAGATION_REQUIRED,-Exception,readOnly");
		// 统计
		transactionAttributes.setProperty("count*", "PROPAGATION_REQUIRED,-Exception,readOnly");

		transactionInterceptor.setTransactionAttributes(transactionAttributes);
		return transactionInterceptor;
	}

	// 代理到ServiceImpl的Bean
	@Bean
	public BeanNameAutoProxyCreator transactionAutoProxy() {
		BeanNameAutoProxyCreator transactionAutoProxy = new BeanNameAutoProxyCreator();
		transactionAutoProxy.setProxyTargetClass(true);
		transactionAutoProxy.setBeanNames("*ServiceImpl");
		transactionAutoProxy.setInterceptorNames("transactionInterceptor");
		return transactionAutoProxy;
	}

}
